import { Loading, Notification } from "element-ui";
import { Toast } from "vant";
import setting from "../config/setting";

let isPhone = false;
if (process.client) {
    window.addEventListener('resize', () => {
        const clientWidth = document.documentElement.clientWidth;
        if (clientWidth < 768) {
            isPhone = true;
        } else {
            isPhone = false;
        }
    })
}

const showToasts = (msg = '请求失败') => {
    if (isPhone) {
        Toast({
            message: msg,
            forbidClick: true,
            duration: 1500
        })
        return
    }
    Notification.error({
        title: '错误',
        message: msg
    })
};

const showLoading = (msg = '正在处理') => {
    let loading = null;
    if (isPhone) {
        loading = Toast.loading({
            message: msg,
            forbidClick: true,
            duration: 0
        })
        return loading
    }
    loading = Loading.service({
        lock: true,
        text: msg,
        spinner: 'el-icon-loading',
        background: 'rgba(0, 0, 0, 0.7)'
    });
    return loading;
}

const hideLoading = (loading) => {
    if (!loading) return;
    if (isPhone) {
        loading.clear();
        return
    }
    loading.close();
}

/**
 * 请求方法
 * @param {Object | String} options 请求参数配置 或者 请求地址
 * @param {String} [options.url] 请求地址
 * @param {String} [options.method] 请求方法
 * @param {Object} [options.data] 请求参数 post
 * @param {Object} [options.params] 请求参数 get
 * @param {Object} [options.headers] 请求头
 * @param {Boolean} [options.loading] 是否显示loading
 * @param {String} [options.loadingMsg] loading提示信息
 * @param {Boolean} [options.uplodFile] 是否是文件上传
 * @param {Boolean} [options.downFile] 是否是文件下载
 * @param {Function} [options.success] 成功回调
 * @param {Function} [options.fail] 失败回调
 * @param {Function} [options.complete] 完成回调
 * @param {String} [method] 请求方法 方便参数传递 调用
 * @param {Object} [data] 请求参数 方便参数传递 调用
 * @param {Function} [callback] 回调函数 方便参数传递 调用
 * @returns {Promise} Promise对象
 * */


function request(option, method, data, callback) {
    let options = {
        url: '',
        method: 'get',
        data: {},
        params: {},
        headers: {},
        loading: false,
        uplodFile: false,
        downFile: false,
        loadingMsg: '正在处理',
        success: (reslut) => { },
        fail: (error) => { },
        complete: () => { }
    };
    if (!option) {
        console.error('请求参数不能为空 本次请求已终止');
        return;
    }
    if (method) options.method = method;
    if (data) options.data = data;
    if (callback) options.success = callback;
    if (typeof option === 'string') {
        options.url = option;
    } else {
        options = Object.assign(options, option);
    }
    if (!options.url) {
        console.error('请求地址不能为空 本次请求已终止');
        return;
    }
    let url = options.url.indexOf('http') === 0 ? options.url : setting.baseUrl + options.url;
    if (options.method.toUpperCase() === 'GET') {
        let params = '';
        for (let key in options.params) {
            params += `${key}=${options.params[key]}&`;
        }
        for (let key in options.data) {
            params += `${key}=${options.data[key]}&`;
        }
        if (params) {
            params = params.substring(0, params.length - 1);
            url += `?${params}`;
        }
        if (url.indexOf('?') === -1) {
            url += '?_t=' + new Date().getTime();
        } else {
            url += '&_t=' + new Date().getTime();
        }
    }
    let fetchOption = {
        method: options.method.toUpperCase(),
        credentials: 'include',
    }
    options.headers ? fetchOption.headers = options.headers : null;
    if (options.method.toUpperCase() !== 'GET') {
        if (!options.uplodFile) {
            options.data._t = new Date().getTime();
        }
        fetchOption.body = options.uplodFile ? options.data : JSON.stringify(options.data);
        fetchOption.headers['Content-Type'] ? null : fetchOption.headers['Content-Type'] = 'application/json';
    }
    let loading = null;
    if (options.loading) {
        loading = showLoading(options.loadingMsg);
    }
    // 设置 Referer
    fetchOption.headers['Referer'] = 'http://localhost:8052'
    return new Promise((resolve, reject) => {
        fetch(url, fetchOption).then(res => {
            if (options.downFile) {
                return res.blob();
            }
            return res.json();
        }).then(res => {
            if (options.downFile) {
                options.success({
                    blob: res,
                    blobUrl: URL.createObjectURL(res)
                });
                options.complete({
                    code: 200,
                    data: {
                        blob: res,
                        blobUrl: URL.createObjectURL(res)
                    }
                });
                resolve({
                    blob: res,
                    blobUrl: URL.createObjectURL(res)
                });
                return;
            }
            if (res.code !== 200) {
                options.fail(res);
                options.complete({
                    code: res.status,
                    data: res.statusText
                });
                reject(res);
                return;
            }
            options.success(res);
            options.complete({
                code: 200,
                data: res
            });
            resolve(res);
        }).catch(error => {
            console.log("错误 ==>", error);
            switch (error.status) {
                case 400:
                    showToasts('请求参数错误');
                    break;
                case 401:
                    showToasts('权限不足');
                    break;
                case 404:
                    showToasts('请求地址不存在');
                    break;
                case 414:
                    showToasts('请求地址过长');
                    break;
                case 415:
                    showToasts('请求类型错误');
                    break;
                case 500:
                    showToasts('服务器错误');
                    break;
                case 502:
                    showToasts('服务器网关错误');
                    break;
                case 504:
                    showToasts('服务器网关超时');
                    break;
                default:
                    showToasts('请求失败');
            }
            options.fail(error);
            options.complete({
                code: error.status,
                data: error.statusText
            });
            reject(error);
        })
    }).finally(() => {
        hideLoading(loading);
    })
}

/**
 * get请求
 * */
request.get = function (options, data, callback) {
    return request(options, 'GET', data, callback);
}

/**
 * post 请求
 * */
request.post = function (options, data, callback) {
    return request(options, 'POST', data, callback);
}

/**
 * put 请求
 * */
request.put = function (options, data, callback) {
    return request(options, 'PUT', data, callback);
}

/**
 * delete 请求
 * */
request.delete = function (options, data, callback) {
    return request(options, 'DELETE', data, callback);
}

if (process.client) {
    window.request = request;
}

export default request;
